home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d21 / dvcron10.arc / CRON.C < prev    next >
Text File  |  1991-12-21  |  12KB  |  437 lines

  1. /*
  2.   Copyright (c) 1991 -- Kyle A. York
  3.   copy / use / modify at will -- see CRON.DOC for details
  4. */
  5.  
  6. #include <dir.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <time.h>
  10. #include <process.h>
  11. #include <fcntl.h>
  12. #include <stdlib.h>
  13. #include <io.h>
  14. #include <tvapi.h>
  15. #include <ctype.h>
  16. #include <sys\stat.h>
  17. #include <alloc.h>
  18. #include "pif.h"
  19. #include "getopt.h"
  20.  
  21. extern int directvideo=0;    /* use BIOS calls for writes */
  22. unsigned _stklen=2048;       /* use a 2K stack (not default 4K) */
  23.  
  24. char *buffer,                /* buffer for CRONTAB file. set once at start */
  25.      crontabname[MAXPATH],   /* full path to 'crontab' */
  26.      cronlogname[MAXPATH],   /* full path to 'cron.log'*/
  27.      crontemplate[MAXPATH];  /* full path to template ".dvp" file */
  28. int  bufsize;                /* size of input buffer   */
  29. time_t now;                  /* current time           */
  30. /*
  31.   this function seems to be missing from the DVGLUE library.
  32.   it pops-up an error window & displays the message. then it waits
  33.   for ESCAPE or a mouse button to be pressed before returning
  34. */
  35. void DVError(char *fmt, ...)
  36. {
  37.   struct REGPACK regs;
  38.   OBJECT         mytask;
  39.   char           errmsg[256],
  40.                 *tmp=errmsg;
  41.   va_list        ap;
  42.   int            rows=1;
  43.  
  44.   va_start(ap, fmt);
  45.   vsprintf(errmsg, fmt, ap);
  46.   va_end(ap);
  47.  
  48.   while (*tmp)                             /* count # of rows used */
  49.     if (*(tmp++) == '\n')                  /* by message */
  50.       rows++;
  51.   mytask=TVmytask();
  52.   regs.r_bx=0x4000 + 0x2000 + strlen(errmsg);
  53.   regs.r_es=FP_SEG(errmsg);
  54.   regs.r_di=FP_OFF(errmsg);
  55.   regs.r_cx=0x5000 | rows;
  56.   regs.r_dx=FP_SEG(mytask);
  57.   regs.r_ax=0x101f;
  58.   intr(0x15, ®s);
  59. }
  60.  
  61. /*
  62.   write info to log file
  63.   (1) open logfile
  64.   (2) write info with timestamp
  65.   (3) close file
  66. */
  67. void cronlog(char *fmt, ...)
  68. {
  69.   FILE   *logfile;
  70.   char    logstr[256];
  71.   va_list ap;
  72.  
  73.   if (!*cronlogname)
  74.     return;
  75.   va_start(ap, fmt);
  76.   vsprintf(logstr, fmt, ap);
  77.   va_end(ap);
  78.   logfile=fopen(cronlogname, "at");
  79.   printf("%24.24s: %s\n", ctime(&now), logstr);
  80.   if (logfile) {
  81.     fprintf(logfile, "%24.24s: %s\n", ctime(&now), logstr);
  82.     fclose(logfile);
  83.   } else
  84.     fprintf(stderr, "cannot open logfile {%s}\n", cronlogname);
  85. }
  86.  
  87. /*
  88.   read the CRON file if necessary
  89.   1st call :         open 'crontab'
  90.   successive calls : check file time with last read, if updated, reread
  91.   note: crontab is open FOR THE DURATION OF THE PROGRAM. it is NEVER closed
  92. */
  93. void ReadCronFile(void)
  94. {
  95.   struct ftime        new;                   /* file time now  */
  96.   static struct ftime old;                   /* last file time */
  97.   static int          handle=-1;
  98.   int                 bytesread;
  99.  
  100.   if (handle < 0) {
  101.     old.ft_day=0;                            /* force new read */
  102.     handle=open(crontabname,                 /* name of file   */
  103.                 O_RDONLY | O_TEXT | O_CREAT, /* used to open normal file */
  104.                 S_IREAD | S_IWRITE);         /* used if file created     */
  105.     if (handle < 0) {                        /* if un-openable, abort    */
  106.       DVError("unable to open crontab file");
  107.       exit(1);
  108.     } else
  109.       cronlog("{%s} opened successfully", crontabname);
  110.   }
  111.   getftime(handle, &new);                    /* get timestamp on file */
  112.   if (memcmp(&new, &old, sizeof(new))) {     /* if unequal, re-read file */
  113.     old=new;                                 /* update last read */
  114.     cronlog("CRONTAB core updated");
  115.     lseek(handle, 0, SEEK_SET);              /* rewind file      */
  116.     bytesread=read(handle, buffer, min(bufsize, filelength(handle)));
  117.     buffer[bytesread]=0;
  118.     if (filelength(handle) >= bufsize)
  119.       cronlog("crontab file overflowed buffer. truncated.");
  120.   }
  121. }
  122.  
  123. /*
  124.   skip string ptr over spaces & tabs
  125.   cannot use isspace() as it also skips c/r, l/f, f/f and some others
  126. */
  127. void SkipSpace(char **spc)
  128. {
  129.   while ((**spc == ' ') || (**spc == 9))
  130.     (*spc)++;
  131. }
  132.  
  133. /*
  134.   skip string ptr over a signed integer
  135. */
  136. void SkipNum(char **spc)
  137. {
  138.   SkipSpace(spc);
  139.   if (**spc == '-')
  140.    (*spc)++;
  141.   while (isdigit(**spc))
  142.     (*spc)++;
  143. }
  144.  
  145. /*
  146.   skip string ptr until a space is found
  147. */
  148. void SkipNonSpc(char **spc)
  149. {
  150.   while (**spc && !isspace(**spc))
  151.     (*spc)++;
  152. }
  153.  
  154. /*
  155.   given a number list
  156.     eg: 1-9,10,12-14
  157.   check that a number is included in the list
  158. */
  159. int IsNumInList(char *s, int num)
  160. {
  161.   int lo, hi;
  162.   char *list=s;
  163.  
  164.   SkipSpace(&list);
  165.   if (*list == '*')
  166.     return(TRUE);
  167.   while (isdigit(*list)) {
  168.     lo=atoi(list);
  169.     SkipNum(&list);
  170.     if (lo == num)
  171.       return(TRUE);
  172.     else if (*list == '-') {
  173.       list++;
  174.       if (!isdigit(*list))
  175.         return(FALSE);
  176.       hi=atoi(list);
  177.       SkipNum(&list);
  178.       if ((lo <= num) && (num <= hi))
  179.         return(TRUE);
  180.     }
  181.     if (*list == ',')
  182.       list++;
  183.   }
  184.   return(FALSE);
  185. }
  186.  
  187. /*
  188.   call IsNumInList(), then skip field
  189. */
  190. int CheckNumInList(char **s, int num)
  191. {
  192.   int tmp;
  193.  
  194.   tmp=IsNumInList(*s, num);
  195.   SkipNonSpc(s);
  196.   SkipSpace(s);
  197.   return(tmp);
  198. }
  199.  
  200. /*
  201.   begin a new task
  202.   assume preceding flags are checked
  203.   this does the extension parsing for how-to-execute
  204. */
  205. int SpawnPif(char *name, char *parms, int minmem, int maxmem,
  206.                   int maxexp, int hiddenflag, int backflag)
  207. {
  208.   int     handle,
  209.           size,
  210.           t;
  211.   DVPtype pif;
  212.   OBJECT  obj;
  213.   char   ext[MAXEXT],
  214.          tmp[128];
  215.  
  216.   fnsplit(name, NULL, NULL, NULL, ext);
  217.  
  218.   t=(stricmp(ext, ".dvp") == 0);
  219.   handle=open(t ? name : crontemplate, O_BINARY | O_RDONLY);
  220.   if (handle < 0) {
  221.     cronlog("cannot open: %s", t ? name : crontemplate);
  222.     return(-1);
  223.   }
  224.   size=read(handle, &pif, sizeof(pif));
  225.   close(handle);
  226.   if (minmem >= 0)
  227.     pif.minmem=minmem;
  228.   if (maxmem >= 0)
  229.     pif.maxmem=maxmem;
  230.   if (maxexp >= 0)
  231.     pif.maxexpanded=maxexp;
  232.   if (backflag >= 0)
  233.     pif.flags4 |= 0x10;
  234.   if (!stricmp(ext, ".com") || !stricmp(ext, ".exe")) {
  235.     strcpy(pif.path, name);
  236.     pif.autocloseonexit=1;
  237.   }
  238.   if (!stricmp(ext, ".bat")) {
  239.     strcpy(tmp, name);
  240.     strcat(tmp, " ");
  241.     strcat(tmp, parms);
  242.   } else
  243.     strcpy(tmp, parms);
  244.   if (strlen(tmp) > 63) {
  245.     cronlog("parameter string > 63 chars {%s} {%s}", name, parms);
  246.     return(-1);
  247.   }
  248.   strcpy(pif.parameters, tmp);
  249.   pif.flags2=0x20 | (*tmp ? 0x40 : 0x00);
  250.   obj=DVapp_start(&pif, size);
  251.   if (obj && hiddenflag)
  252.     TVapp_hide(obj);
  253.   if (obj)
  254.     cronlog("%s spawned as %08lx", name, obj);
  255.   else
  256.     cronlog("%s <<SPAWN FAILED>>", name);
  257.   return(0);
  258. }
  259.  
  260. /*
  261.   replace all occurences of rep in str with 2-digit val
  262. */
  263. void Replace(char *str, char *rep, int val)
  264. {
  265.   char *ptr, tmp[3];
  266.  
  267.   do {
  268.     ptr=strstr(str, rep);
  269.     if (ptr) {
  270.       sprintf(tmp, "%02d", val);
  271.       memcpy(ptr, tmp, 2);
  272.     }
  273.   } while (ptr);
  274. }
  275.  
  276. /*
  277.   this does the pre-parsing.
  278. */
  279. void Execute(char *s, struct tm *tm)
  280. {
  281.   char cmd[64],
  282.        param[64],
  283.        *ptr=s,
  284.        done=0;
  285.   int  ii=0,
  286.        minmem=-1,    /* minimum conventional memory required */
  287.        maxmem=-1,    /* maximum conventional memory allowed */
  288.        maxexp=-1,    /* maximum expanded memory allowed */
  289.        num,          /* temp number for conventional memory */
  290.        hiddenflag=0, /* 1 = yes */
  291.        backflag=-1;  /* 1 = start in background,
  292.                         0 = start in foreground,
  293.                         -1 = use default */
  294.  
  295.   do {                   /* parse for prefixes */
  296.     SkipSpace(&ptr);
  297.     if (*ptr == '-') {
  298.       ptr++;
  299.       switch(*(ptr++)) {
  300.         case 'b': backflag=1; break;
  301.         case 'c': num=atoi(ptr);
  302.                   SkipNum(&ptr);
  303.                   if (num < 0)
  304.                     minmem=-num;
  305.                   else
  306.                     maxmem=num;
  307.                   break;
  308.         case 'e': maxexp=atoi(ptr);
  309.                   SkipNum(&ptr);
  310.                   break;
  311.         case 'h': hiddenflag=1;
  312.                   break;
  313.         default:  ptr-=2;
  314.                   done=1;
  315.                   break;
  316.       }
  317.     } else
  318.       done=1;
  319.   } while (!done);
  320.   while (*ptr && !isspace(*ptr) && (ii < 64)) {     /* copy command */
  321.     cmd[ii++]=*ptr;
  322.     ptr++;
  323.   }
  324.   if (ii >= 64) {
  325.     cronlog("program name > 63 characters {%s}", s);
  326.     return;
  327.   }
  328.   cmd[ii]=0;
  329.   SkipSpace(&ptr);                       /* skip spaces */
  330.   ii=0;                                  /* everything to end-of-line */
  331.   while (*ptr && (*ptr != '\n') && (ii < 64)) {       /* are parameters for the command */
  332.     param[ii++]=*ptr;
  333.     ptr++;
  334.   }
  335.   if (ii >= 64) {
  336.     cronlog("parameters > 63 characters {%s}", s);
  337.     return;
  338.   }
  339.   param[ii]=0;
  340.   Replace(param, "%M", tm->tm_mon+1);  /* do necessary parameter */
  341.   Replace(param, "%D", tm->tm_mday);   /* replacements */
  342.   Replace(param, "%h", tm->tm_hour);
  343.   Replace(param, "%m", tm->tm_min);
  344.   SpawnPif(cmd, param, minmem, maxmem, maxexp, hiddenflag, backflag);
  345. }
  346.  
  347. /*
  348.   this is the loop where stuff actually gets done.
  349.   it checks the core image to see if anything is ready
  350.   to be spawned & sends the necessary data for spawning
  351. */
  352. void DoCronStuff(struct tm *tm)
  353. {
  354.   char *bufptr=buffer,
  355.         tmp;
  356.  
  357.   while (*bufptr) {
  358.     if (CheckNumInList(&bufptr, tm->tm_min) &&
  359.         CheckNumInList(&bufptr, tm->tm_hour)) {
  360.       tmp=CheckNumInList(&bufptr, tm->tm_mday);
  361.       if (CheckNumInList(&bufptr, tm->tm_mon))
  362.         if (CheckNumInList(&bufptr, tm->tm_wday) || tmp)
  363.           Execute(bufptr, tm);
  364.     }
  365.     while ((*bufptr != '\n') && *bufptr)
  366.       bufptr++;
  367.     if (*bufptr == '\n')
  368.       bufptr++;
  369.   }
  370. }
  371.  
  372. void main(int argc, char **argv)
  373. {
  374.   struct tm *tm;                /* structure for more readable time */
  375.   OBJECT     timer;             /* TV timer object */
  376.   char       drive[MAXDRIVE],   /* path to CRON.EXE */
  377.              dir[MAXDIR];
  378.   int        key,
  379.              errflag;
  380.  
  381.   DVinit();                        /* initialize DV functions */
  382.  
  383.   bufsize=1024;
  384.   fnsplit(argv[0], drive, dir, NULL, NULL);
  385.   fnmerge(crontabname, drive, dir, "crontab", NULL);
  386.   fnmerge(cronlogname,  drive, dir, "cron", ".log");
  387.   fnmerge(crontemplate, drive, dir, "crondos", ".dvp");
  388.  
  389.   errflag=0;
  390.   while ((key=getopt(argc, argv, "c:d:l:m:")) != EOF) {
  391.     switch(key) {
  392.       case 'c': strcpy(crontabname, optarg); break;
  393.       case 'd': strcpy(crontemplate, optarg); break;
  394.       case 'l': if (!stricmp(optarg, "-"))
  395.                   *cronlogname=0;
  396.                 else
  397.                   strcpy(cronlogname, optarg);
  398.                 break;
  399.       case 'm': bufsize=atoi(optarg);
  400.                 break;
  401.       default:  errflag=1;
  402.                 break;
  403.     }
  404.   }
  405.   if (errflag) {
  406.     DVError("format:\n\r   %s [-c crontabname] [-d crontemplate] [-l-] "
  407.             "[-l logfilename] [-m memsize]",
  408.              argv[0]);
  409.     exit(1);
  410.   }
  411.   printf("Buffer size: %d\n", bufsize);
  412.   printf("CRONTAB:     %s\n", crontabname);
  413.   printf("Log file:    %s\n", cronlogname);
  414.   printf("Template:    %s\n", crontemplate);
  415.  
  416.   if (!(buffer=malloc(bufsize))) {              /* allocate buffer */
  417.     DVError("Could not allocate CRONTAB buffer");
  418.     exit(1);
  419.   }
  420.   if (access(crontemplate, 0)) {                /* check that template */
  421.     DVError("Template not found {%s}", crontemplate); /* exists */
  422.     exit(1);
  423.   }
  424.  
  425.   timer=TVtimer_new();             /* initialize timer        */
  426.   do {
  427.     time(&now);                                  /* get current time     */
  428.     tm=localtime(&now);                          /* in structure         */
  429.     TVtimer_begin(timer, 100*(60-tm->tm_sec));   /* start countdown until
  430.                                                     next minute */
  431.     ReadCronFile();                              /* load the CRON file */
  432.     DoCronStuff(tm);                             /* execute instructions */
  433.     TVtimer_wait(timer);                         /* give-up CPU until
  434.                                                     counter reaches 0 */
  435.   } while (1);                                   /* repeat indefinetly */
  436. }
  437.